#region Using directives
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using BoOnce.Core.Helpers;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace BoOnce.Core.Components
{
    public class FPSComponent : DrawableGameComponent
    {
        #region Constantes
        private const int LOW_FPS = 45;
        private const float AVERAGE_ON = 200; //ms
        private const float SECOND = 1000f; //ms
        #endregion

        #region Private Attributes
        private SpriteBatch _SpriteBatch;
        private SpriteFont _Font;
        private Vector2 _InstantPos = new Vector2(0.2f, 0.2f);
        private Vector2 _UpdatePos = new Vector2(0.2f, 15.0f);
        private Vector2 _AveragePos = new Vector2(0.2f, 28.8f);

        private int _UpdatePerSecondBuffer = 0;
        private double _UpdatePerSecondTimer = 0;
        private int _UpdatePerSecond = 0;

        private int _FramePerSecondBuffer = 0;
        private double _FramePerSecondTimer = 0;
        private int _FramePerSecond = 0;
        #endregion

        #region Constructor
        public FPSComponent(Game game)
            : base(game){}
        #endregion

        #region DrawableGameComponent
        public override void Initialize()
        {
            _SpriteBatch = new SpriteBatch(Game.GraphicsDevice);
            base.Initialize();
            Logger.WriteInfo("FPSComponent[#" + this.UpdateOrder + "] init");
        }

        public override void Update(GameTime gameTime)
        {
            // Compute Update Per Second
            if (_UpdatePerSecondTimer < gameTime.TotalGameTime.TotalMilliseconds)
            {
                _UpdatePerSecondTimer = gameTime.TotalGameTime.TotalMilliseconds + AVERAGE_ON;
                _UpdatePerSecond = (int)(_UpdatePerSecondBuffer * (SECOND/AVERAGE_ON));
                _UpdatePerSecondBuffer = 0;
            }
            else
            {
                _UpdatePerSecondBuffer++;
            }
            base.Update(gameTime);
        }

        protected override void LoadContent()
        {
            _Font = Game.Content.Load<SpriteFont>("Fonts/Arial8");
        }

        public override void Draw(GameTime gameTime)
        {
            // compute instant FPS
            int instantFPS = (int)(SECOND / gameTime.ElapsedGameTime.TotalMilliseconds);

            // compute average FPS
            if (_FramePerSecondTimer < gameTime.TotalGameTime.TotalMilliseconds)
            {
                _FramePerSecondTimer = gameTime.TotalGameTime.TotalMilliseconds + AVERAGE_ON;
                _FramePerSecond = (int)(_FramePerSecondBuffer * (SECOND/AVERAGE_ON));
                _FramePerSecondBuffer = 0;
            }
            else
            {
                _FramePerSecondBuffer++;
            }

            // Detect low FPS
            Color textColor = Color.White;
            if (instantFPS < LOW_FPS)
            {
                textColor = Color.Red;
                Logger.WriteWarning("Low FPS detectd:" + instantFPS);
            }

            _SpriteBatch.Begin();
            _SpriteBatch.DrawString(_Font, "Instant FPS:" + instantFPS, _InstantPos, textColor);
            _SpriteBatch.DrawString(_Font, "Average FPS:" + _FramePerSecond, _AveragePos, Color.White);
            _SpriteBatch.DrawString(_Font, "UPS:" + _UpdatePerSecond, _UpdatePos, Color.White);
            _SpriteBatch.End();
        }
        #endregion
    }
}